#define _GNU_SOURCE
#include "daemon_sub_process.h"
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/reboot.h>
#include <signal.h>
#include "log/log.h"

SubProcess *daemon_sub_process_init(char *cmd_param)
{
    SubProcess *sp = malloc(sizeof(SubProcess));
    sp->cmd_param = cmd_param;
    sp->pid = -1;
    sp->fail_count = 0;

    return sp;
}

int daemon_sub_process_checkStart(SubProcess *sp)
{
    // 检查目标子进程是否正在运行中，如果在运行，直接正常结束
    // WNOHANG: 不会等待子进程结束才返回
        // 如果子进程正在运行，立即返回0
        // 如果子进程当前没运行，前面退出，就将进程退出的状态值保存到result中，返回非0
    int result = 0;
    if(sp->pid>0 && waitpid(sp->pid, &result, WNOHANG)==0) {
        log_debug("进程(%s)正在运行中，无需启动", sp->cmd_param);
        return 0;
    }
    // 如果是运行过，但现在没有运行，说明是意外结束，记录失败的次数，如果超过了限定值，重启系统
    if (result!=0) {
        sp->fail_count++;
        if (sp->fail_count > MAX_FAIL_COUNT) {
            reboot(RB_AUTOBOOT);
        }
    }

    // 创建一个子进程，并运行目标程序
    sp->pid = fork();
    if (sp->pid == 0) {
        log_debug("在子进程中运行目标程序(%s)", sp->cmd_param);
        char *argv[] = {EXE_PATH, sp->cmd_param, NULL};
        execve(EXE_PATH, argv, NULL);
        // 如果没有找到目标程序执行，结束当前子进程
        _exit(EXIT_FAILURE);
    }

    return 0;
}

void daemon_sub_process_stop(SubProcess *sp)
{
    // 杀死子进程, 发送SIGTERM信号给子进程
    kill(sp->pid, SIGTERM);
    // 等待子进程结束
    waitpid(sp->pid, NULL, 0);
    // 释放sp
    free(sp);
}
